import axios from 'axios';

export type ApiResponse<DataType> = {
  code: number;
} & ({
  error: string;
  data: null;
} | {
  error: null;
  data: DataType;
});
export const parseApiResponse = <DataType, >(resp: { code: number } & ({ error: string; data: null } | { error: null; data: DataType })) => {
  if ('error' in resp && resp.error != null) return { error: resp.error, data: null, code: resp.code };
  return { error: null, data: resp.data, code: resp.code };
}
export const fromError = (error: unknown, code: number = -1) => ({ code, error: error instanceof Error ? error.message : error + '', data: null });
export const fromData = <DataType, >(data: DataType, code: number = 0) => ({ code, error: null, data });

export function initAxios() {
  const instance = axios.create({
    validateStatus: () => true,
  });
  instance.interceptors.request.use(async config => {
    if (config.data) {
      if (config.data instanceof File) {
        config.headers['Content-Type'] = config.data.type;
        config.data = await config.data.arrayBuffer();
      } else if (config.data instanceof ArrayBuffer || config.data instanceof Blob) {
        config.headers['Content-Type'] = 'application/octet-stream';
      } else if (config.data instanceof FormData) {
        config.headers['Content-Type'] = 'multipart/form-data';
      } else {
        config.headers['Content-Type'] = 'application/json';
      }
    }
    return config;
  });
  instance.interceptors.response.use(response => {
    if (response.status >= 400 || response.data.code !== 0) {
      response.data = fromError(response.data.error ?? response.statusText, response.data.code);
    } else {
      response.data = fromData(response.data.data);
    }
    return response;
  }, error => {
    return fromError(error);
  });
  return instance;
}
